<template>
  <!-- 图片上传 -->
  <div class="uploadWrapper">
    <div class="boxTitle">
      <div class="title">
        <span>图片上传</span>
        <span class="number"
          >{{ uploadImgList.length }} / {{ uploadImgMaxNum }}</span
        >
      </div>
      <div class="close" @click="closeUploadBox">
        <i class="iconfont icon-guanbi"></i>
      </div>
    </div>
    <div class="boxBody">
      <div class="listbox">
        <div class="selectImgList" ref="selectImglist">
          <div
            class="selectImg"
            :class="[
              item.swappable ? 'swap' : '',
              item.draggable ? 'drag' : '',
              item.movable ? 'move' : '',
            ]"
            v-for="(item, index) in uploadImgList"
            :draggable="item.draggable"
            :style="{ ...item.style }"
          >
            <div
              class="img"
              @mousedown="imgmousedownCB(index)"
              :style="{
                background: `url(${item.path})`,
              }"
            ></div>
            <div class="close" @click="deleteImg(index)">
              <i class="iconfont icon-guanbi"></i>
            </div>
          </div>
          <div
            class="upload"
            @click="upload"
            v-if="uploadImgList.length < uploadImgMaxNum"
            title="未选择上传文件"
          >
            <i class="iconfont icon-tianjia1"></i>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    uploadImgMaxNum: {
      typeof: Number,
      required: false,
      default: 9,
    },
    allowDrag: {
      typeof: Boolean,
      required: false,
      default: true,
    },
    allowOpenUpload: {
      typeof: Boolean,
      required: false,
      default: false,
    },
  },
  data() {
    return {
      $imgList: null, //图片列表节点对象
      uploadImgList: [], //
      dragImgIndex: 0, //拖拽中的图片下标
      moveToImgIndex: 0, //拖拽终点的图片下标
      imgtransitionTime: 500, //图片变形时间ms
      dragImgLeft: 0, //拖拽中的图片左偏移
      dragImgTop: 0, //拖拽中的图片上偏移
    };
  },
  mounted() {
    if (this.allowOpenUpload) {
      this.upload();
    }
    if (this.uploadImgMaxNum > 9 || this.uploadImgMaxNum <= 0) {
      throw new Error("请正确输入上传最大值1~9");
    }
    this.$imgList = this.$refs.selectImglist;
    if (this.allowDrag) {
      this.$imgList.addEventListener("dragstart", (e) => {
        for (let [index, item] of Object.entries(this.$imgList.children)) {
          if (item == e.target) {
            this.dragImgIndex = index;
            this.dragImgLeft = this.uploadImgList[index].minLeft;
            this.dragImgTop = this.uploadImgList[index].minTop;
            break;
          }
        }
      });
      this.$imgList.addEventListener("drag", (e) => {
        //阻止默认事件，防止以链接释放
        e.preventDefault();
        let { offsetX, offsetY } = e;
        offsetX += this.dragImgLeft;
        offsetY += this.dragImgTop;
        for (let [index, item] of Object.entries(this.uploadImgList)) {
          if (
            offsetX >= item.minLeft &&
            offsetX < item.maxLeft &&
            offsetY >= item.minTop &&
            offsetY < item.maxTop
          ) {
            this.moveToImgIndex = index;
            this.swapImg(this.dragImgIndex, this.moveToImgIndex);
            break;
          }
        }
      });
      this.$imgList.addEventListener("dragover", (e) => {
        // 阻止默认事件，允许释放拖拽
        e.preventDefault();
      });
      this.$imgList.addEventListener("dragend", () => {
        this.$set(this.uploadImgList[this.dragImgIndex], "draggable", false);
      });
    }
    this.watchGetUploadImageList()
  },
  methods: {
    closeUploadBox() {
      this.$emit("close");
    },
    deleteImg(index) {
      this.uploadImgList.splice(index, 1);
      this.getImgListPosition();
    },
    upload() {
      uni.chooseImage({
        count: this.uploadImgMaxNum, //默认9
        sizeType: ["original", "compressed"], //可以指定是原图还是压缩图，默认二者都有
        sourceType: ["album"], //从相册选择
        success: (res) => {
          let { tempFilePaths: list } = res;
          for (let [index, item] of Object.entries(list)) {
            if (this.uploadImgList.length >= 9) break;
            let obj = {
              draggable: false,
              path: item,
            };
            this.uploadImgList.push(obj);
          }
          this.getImgListPosition();
        },
      });
    },
    getImgListPosition() {
      this.$nextTick(() => {
        this.$imgList.childNodes.forEach((item, index) => {
          if (index < this.uploadImgList.length) {
            let imgObj = this.uploadImgList[index];
            this.$set(imgObj, "minLeft", item.offsetLeft);
            this.$set(imgObj, "minTop", item.offsetTop);
            this.$set(imgObj, "maxTop", item.offsetHeight + item.offsetTop);
            this.$set(imgObj, "maxLeft", item.offsetWidth + item.offsetLeft);
            this.$set(imgObj, "draggable", false);
          }
        });
      });
    },
    swapImg(dragIndex, toIndex) {
      if (dragIndex == toIndex) return;
      const DRAG = this.uploadImgList[dragIndex];
      const TO = this.uploadImgList[toIndex];
      if (TO.swappable) return; //防止触发两次
      if (DRAG.swappable) return; //防止触发两次
      let drag_path = DRAG.path;
      let to_path = TO.path;
      let drag_minLeft = DRAG.minLeft;
      let drag_minTop = DRAG.minTop;
      let to_minLeft = TO.minLeft;
      let to_minTop = TO.minTop;
      this.$set(DRAG, "path", to_path);
      this.$set(TO, "path", drag_path);
      let translateX = drag_minLeft - to_minLeft;
      let translateY = drag_minTop - to_minTop;
      /*添加动画*/
      // 终点动画
      let endtyle = {
        transition: `transform ${this.imgtransitionTime}ms ease 0s`,
        transform: `translate3d(0px,0px,0px)`,
      };
      // 移动时动画
      let drag_swapStyle = {
        transform: `translate3d(${-translateX}px,${-translateY}px,0px)`,
      };
      let to_swapStyle = {
        transform: `translate3d(${translateX}px,${translateY}px,0px)`,
      };
      // 创建专属定时器删除style 和 修改状态
      if (!DRAG.timeout) {
        DRAG.timeout = setTimeout(() => {
          this.$set(DRAG, "swappable", false);
          this.$set(DRAG, "movable", false);
          this.$set(DRAG, "style", null);
          clearTimeout(DRAG.timeout);
          DRAG.timeout = null;
        }, this.imgtransitionTime);
      }
      if (!TO.timeout) {
        TO.timeout = setTimeout(() => {
          this.$set(TO, "swappable", false);
          this.$set(TO, "movable", false);
          this.$set(TO, "style", null);
          clearTimeout(TO.timeout);
          TO.timeout = null;
        }, this.imgtransitionTime);
      }
      this.$set(DRAG, "swappable", true);
      this.$set(TO, "swappable", true);
      this.$set(DRAG, "style", drag_swapStyle);
      this.$set(TO, "style", to_swapStyle);
      this.dragImgIndex = toIndex;
      this.getImgListPosition();
      this.$nextTick(() => {
        this.$set(TO, "style", endtyle);
        this.$set(DRAG, "style", endtyle);
        // 触发变形
        this.$set(TO, "movable", true);
        this.$set(DRAG, "movable", true);
      });
    },
    imgmousedownCB(index) {
      let img = this.uploadImgList[index];
      this.$set(img, "draggable", true);
    },
    // 监听获取图片数据事件
    watchGetUploadImageList() {
      this.$bus.$on("getUploadImageList", () => {
        this.$emit(
          "send",
          this.uploadImgList.map((item) => item.path)
        );
      });
    },
  },
};
// 评论发布-(触发)->图片返回数据-（触发）->评论接收
</script>

<style lang="scss">
.uploadWrapper {
  position: absolute;
  top: 30px;
  left: -10px;
  width: 296px;
  background-color: #fff;
  border-radius: 10px;
  box-shadow: 0 2px 8px rgba(83, 83, 83, 0.384);
  z-index: 8;
  &::before {
    content: "";
    position: absolute;
    width: 10px;
    height: 10px;
    border-radius: 2px 0 0 0;
    left: 16px;
    top: -5px;
    transform: rotate(45deg);
    background-color: #fff;
    box-shadow: 1px 1px 4px rgba(83, 83, 83, 0.384);
  }
  &::after {
    content: "";
    position: absolute;
    width: 20px;
    height: 10px;
    left: 11px;
    top: 0;
    background-color: #ffffff;
  }
  .boxTitle {
    width: 296px;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    padding: 15px;
    font-family: Helvetica Neue, Helvetica, Arial, Microsoft Yahei,
      Hiragino Sans GB, Heiti SC, WenQuanYi Micro Hei, sans-serif;
    font-size: 14px;
    box-sizing: border-box;
    .number {
      color: #c0c0c0;
      margin-left: 10px;
    }
    .close {
      color: rgb(180, 180, 180);
      font-size: 18px;
      cursor: pointer;
    }
  }
  .boxBody {
    padding: 0 12px;
    .listbox {
      width: 100%;
      position: relative;
      .selectImgList {
        width: 270px;
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        padding: 0;
        position: relative;
        .selectImg {
          height: 80px;
          width: 80px;
          margin: 0 0 10px 10px;
          position: relative;
          background-color: rgb(240, 240, 240);
          cursor: move;
          &:hover .close {
            opacity: 1;
          }
          .img {
            width: 100%;
            height: 100%;
            background-size: 100% 100% !important;
            background-position: center center !important;
          }
          .close {
            position: absolute;
            right: 0;
            top: 0;
            width: 20px;
            height: 20px;
            background-color: rgba(65, 65, 65, 0.705);
            color: #fff;
            text-align: center;
            line-height: 20px;
            font-size: 12px;
            cursor: pointer;
            opacity: 0;
            transition: opacity 200ms linear 0s;
          }
        }
        .upload {
          border: 2px #c0c0c0 dashed;
          width: 80px;
          height: 80px;
          margin: 0 0 10px 10px;
          color: #c0c0c0;
          font-size: 40px;
          text-align: center;
          line-height: 73px;
          transition: color 0.5s, border 0.5s;
          position: relative;
          .icon-tianjia1{
            font-size: 28px;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%,-50%);
          }
          &:hover {
            border: 2px #00a1d6 dashed;
            color: #00a1d6;
            transition: color 0.5s, border 0.5s;
          }
        }
      }
    }
  }
}
</style>